package top.truism.array;

import java.util.Objects;

/**
 * 名人问题
 * 所有人都认识名人，名人不认识除了自己的所有人
 */
public class StarsQuestion {

    /**
     * 查询人群中的名人
     *
     * @param celebrities
     * @return
     */
    public static Celebrity findCelebrity(Celebrity[] celebrities) {
        if (celebrities == null || celebrities.length == 0) {
            return null;
        }
        Celebrity candidate = celebrities[0];
        for (int i = 1; i < celebrities.length; i++) {
            // 当前候选人认识其他人，则他一定不是名人,不认识则其他人一定不是名人
            if (candidate.knowsOther(celebrities[i])) {
                candidate = celebrities[i];
            }
        }
        // 确定名人候选人，确认所有人都认识他
        for (int i = 0; i < celebrities.length; i++) {

            if (candidate != celebrities[i] && celebrities[i].knowsOther(candidate)) {
                continue;
            } else if (candidate != celebrities[i]) {
                return null;
            }

        }
        // 确认他不认识其他所有人
        for (int i = 0; i < celebrities.length; i++) {
            if (candidate != celebrities[i] && !candidate.knowsOther(celebrities[i])) {
                continue;
            } else if (candidate != celebrities[i]) {
                return null;
            }
        }
        return candidate;
    }

    /**
     * 定义名人类
     */
    public static class Celebrity {

        String name;

        boolean isCelebrity;

        public Celebrity(String name, boolean isCelebrity) {
            this.isCelebrity = isCelebrity;
            this.name = name;
        }

        boolean knowsOther(Celebrity celebrity) {
            return !isCelebrity && celebrity.isCelebrity;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (!(o instanceof Celebrity)) return false;
            Celebrity celebrity = (Celebrity) o;
            return isCelebrity == celebrity.isCelebrity &&
                    name.equals(celebrity.name);
        }

        @Override
        public int hashCode() {
            return Objects.hash(name, isCelebrity);
        }
    }

}
